package com.i72.freeway;

import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author jiangj
 * @version 1.0.0
 * @ClassName HandleParam.java
 * @Description TODO
 * @createTime 2021年12月28日 15:49:00
 */
@Getter
@Setter
public class HandleParam {

    private static final Map<String, HandleParam> cache = new ConcurrentHashMap<>();

    /**
     * 接口的版本号
     */
    private String version;

    /**
     * 和command同义，apiName/methodName
     */
    private String servicePath;

    /**
     * 接口名字
     */
    private String apiName;

    /**
     * 服务节点，取自package
     */
    private String appNode;

    /**
     * 接口的返回类型。用于反序列化
     */
    private Type genericReturnType;

    /**
     * 接口的超时时间。暂时仅适用于方法级别
     */
    private int timeout;

    /**
     * FreewayPath配置项，可指定服务节点，不为空则会取代appNode
     */
    private String serviceNode;

    /**
     * 接口的返回类型。
     */
    private Class returnType;

    /**
     * rpc调用的服务节点名称，serviceName = StringUtils.defaultIfBlank(serviceNode, appNode);
     */
    private String serviceName;

    /**
     * 方法标记。用于序列化脱敏。
     */
    private String methodKey;

    /**
     * 结果是否封装默认结构体
     * @see com.swj.basic.dto.ResultWrap
     */
    private boolean isResultWrap = true;

    public static HandleParam copyFromCache(Class clazz, Method method) {
        String key = clazz.getName() + "." + method.getName();
        if (cache.containsKey(key)) {
            return ObjectHelper.copy(cache.get(key), HandleParam.class);
        }
        return ObjectHelper.copy(getHandleParam(clazz, method), HandleParam.class);
    }

    public static HandleParam getHandleParam(Class clazz, Method method) {
        String key;
        /*
        if (apiVersion == null) {
            key = clazz.getName() + "." + method.getName();
        } else {
            key = clazz.getName() + "." + method.getName() + "." + apiVersion.getVersion();
        }*/
        key = clazz.getName() + "." + method.getName();
        if (cache.containsKey(key)) {
            return cache.get(key);
        }

        FreewayPath classPath = (FreewayPath) clazz.getAnnotation(FreewayPath.class);
        FreewayPath methodPath = method.getAnnotation(FreewayPath.class);
        HandleParam handleParam = new HandleParam();
        handleParam.setApiName(clazz.getName());
        String apiName;
        String methodName;
        // 接口名
        if (StringUtils.isEmpty(classPath.value())) {
            apiName = StringHelper.removeEnd(clazz.getSimpleName(), "Service");
            apiName = StringHelper.toLowerCaseFirstOne(apiName);
        } else {
            apiName = classPath.value();
        }
        // 方法名
        if (methodPath == null || StringHelper.isNullOrEmpty(methodPath.value())) {
            methodName = StringHelper.toLowerCaseFirstOne(method.getName());
        } else {
            methodName = methodPath.value();
        }
        handleParam.setResultWrap(classPath.isResultWrap());
        // 超时时间
        if (methodPath != null) {
            handleParam.setTimeout(methodPath.timeout());
            handleParam.setServiceNode(methodPath.serviceNode());
            handleParam.setResultWrap(methodPath.isResultWrap());
        }
        // 版本号
        /*
        if (apiVersion != null) {
            handleParam.setVersion("/" + apiVersion.getVersion());
        }*/
        handleParam.setServicePath(apiName + "/" + methodName);
        handleParam.setAppNode(ClassUtils.getAppNode(clazz));
        handleParam.setReturnType(method.getReturnType());
        handleParam.setGenericReturnType(method.getGenericReturnType());
        handleParam.setMethodKey(clazz.getName() + "." + method.getName());
        if (StringHelper.isNullOrEmpty(handleParam.getServiceNode())) {
            handleParam.setServiceNode(classPath.serviceNode());
        }

        String name = "";
        if(StringUtils.isEmpty(handleParam.getServiceNode())){
            name = handleParam.getAppNode();
        }else{
            name = handleParam.getServiceNode();
        }
        handleParam.setServiceName(name);
        //handleParam.setServiceName(StringUtils.defaultIfBlank(handleParam.getServiceNode(), handleParam.getAppNode()));
        cache.put(key, handleParam);
        return handleParam;
    }

}
